#pragma once

#include "CrossDefine.h"
#include <map>
#include <string>
#include <vector>
#include "FileOP.h"

typedef void ( *CSV_CHEAT_DETECT_CALLBACK)		(int chect);
void	set_csv_cheat_detect_callback(CSV_CHEAT_DETECT_CALLBACK func);
int		str_check(const char* str, int len);

class CCsv_base
{
public:
	virtual const char*		getString( const char* szField, const char* szKey, const char* szDefault = "" )	= 0;
	virtual const char*		getString( int idxField, int idxKey, const char* szDefault = "" )	= 0;
	virtual const char*		getString( const char* szField, int idxLine, const char* szDefault = "" )	= 0;

	virtual int				get_long( const char* szField, const char* szKey, const char* szDefault = "0" )	= 0;
	virtual int				get_long( int idxField, int idxKey, const char* szDefault = "0" )	= 0;
	virtual int				get_long( const char* szField, int idxLine, const char* szDefault = "0" )	= 0;

	virtual unsigned long	get_hex( const char* szField, const char* szKey, const char* szDefault = "0" )	= 0;
	virtual unsigned long	get_hex( int idxField, int idxKey, const char* szDefault = "0" )	= 0;
	virtual unsigned long	get_hex( const char* szField, int idxLine, const char* szDefault = "0" )	= 0;

	virtual float			get_float( const char* szField, const char* szKey, const char* szDefault = "0" )	= 0;
	virtual float			get_float( int idxField, int idxKey, const char* szDefault = "0" )	= 0;
	virtual float			get_float( const char* szField, int idxLine, const char* szDefault = "0" )	= 0;

	virtual int				getFieldIndex(const char* szField)	= 0;
	virtual int				getKeyIndex(const char* szKey)	= 0;
	virtual int				getFieldCount()	= 0;
	virtual int				getLineCount()	= 0;
	virtual bool			Load(const char* str_file)	= 0;
protected:
};


class CCsv : public CCsv_base
{
public:
	const char*		getString( const char* szField, const char* szKey, const char* szDefault = "" );
	const char*		getString( int idxField, int idxKey, const char* szDefault = "" );
	const char*		getString( const char* szField, int idxLine, const char* szDefault = "" );

	int				get_long( const char* szField, const char* szKey, const char* szDefault = "0" );
	int				get_long( int idxField, int idxKey, const char* szDefault = "0" );
	int				get_long( const char* szField, int idxLine, const char* szDefault = "0" );

	unsigned long	get_hex( const char* szField, const char* szKey, const char* szDefault = "0" );
	unsigned long	get_hex( int idxField, int idxKey, const char* szDefault = "0" );
	unsigned long	get_hex( const char* szField, int idxLine, const char* szDefault = "0" );

	float			get_float( const char* szField, const char* szKey, const char* szDefault = "0" );
	float			get_float( int idxField, int idxKey, const char* szDefault = "0" );
	float			get_float( const char* szField, int idxLine, const char* szDefault = "0" );

	int				getFieldIndex(const char* szField);
	int				getKeyIndex(const char* szKey);
	int				getFieldCount();
	int				getLineCount();
	
	int				add_Field(const char* szField);
	int				add_String(const char* szBuf, const char* szField, int idxLine = -1);
	int				add_Long(int nVal, const char* szField, int idxLine = -1);
	int				add_Float(float fVal, const char* szField, int idxLine = -1);

	virtual bool	SaveBegin(const char* str_file);
	virtual int		SaveField(std::vector <std::string>& line);
	virtual int		SaveLine(std::vector <std::string>& line);
	virtual bool	SaveEnd();

	void			cleanup();
	bool			Load(const char* str_file);
	bool			Save(const char* str_file);
	bool			LoadFromBuf(GSFBUF &gsf);

	CCsv();
	CCsv(char const *str_file, bool is_check=true);
	virtual ~CCsv();

protected:
	typedef std::map<std::string, int>	MAP_FIELD;
	typedef std::vector<std::string>	MAP_LINE;
	typedef std::vector<MAP_LINE>		MAP_DATA;
	typedef std::vector<int>			MAP_LINE_C;
	typedef std::vector<MAP_LINE_C>		MAP_DATA_C;

	static const int MAX_CFG_LINE_LEN = 4096;

	std::string		m_name;
	MAP_FIELD		m_map_field_idx;
	MAP_FIELD		m_map_line_idx;
	MAP_DATA		m_map_data;
	MAP_DATA_C		m_map_data_c;
	bool			m_is_check;
	bool			m_is_check_failed;

	// save use
	GSFBUF			m_gsf;
};

